home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_10_03 / cmenu.exe / RMENU2.C < prev    next >
Text File  |  1992-01-30  |  8KB  |  377 lines

  1. /************************************************************
  2.  *    Program: RMENU Menu Interpreter
  3.  *  Module: rmenu2.c
  4.  *    Top-level menu processing
  5.  *    Written by: Leor Zolman, 7/91
  6.  ************************************************************/
  7.  
  8. #include "cmenu.h"
  9. #include "rcmenu.h"
  10.  
  11. #if __STDC
  12. #pragma hdrstop
  13. #endif
  14.  
  15. #include <ctype.h>
  16.  
  17.  
  18. /************************************************************
  19.  * sub_menu(): 
  20.  *    Run a local menu at the given nesting level
  21.  *    Default command/menu path is supplied via "path".
  22.  ************************************************************/
  23.  
  24. int sub_menu(mnum, path)
  25. int mnum;
  26. char *path;
  27. {
  28.     MENU2 *M2p = LMenus[nestlev].Menus[mnum];
  29.     MENU *Mp = &M2p -> Menu;
  30.     char newpath[MAX_PATH];
  31.     
  32.     int cur_item = 0;
  33.     int sel_val = 0;
  34.     int factor;
  35.     
  36.     draw_menu(M2p, cur_item);        /* display the menu        */
  37.  
  38.     strcpy(newpath, make_path(path, Mp -> path));
  39.  
  40.     while (1)
  41.     {
  42.         switch (get_cmd(Mp -> nitems, cur_item, &sel_val))
  43.         {
  44.             case  KEY_UP:
  45.                 draw_item(M2p, cur_item, NORMAL, NO);
  46.                 cur_item = cur_item ? cur_item - 1 :
  47.                         Mp -> nitems - 1;
  48.                 draw_item(M2p, cur_item, STANDOUT, YES);
  49.                 break;
  50.                 
  51.             case KEY_DOWN:
  52.                 draw_item(M2p, cur_item, NORMAL, NO);
  53.                 cur_item = (cur_item == Mp -> nitems - 1) ? 0 :
  54.                         cur_item + 1;
  55.                 draw_item(M2p, cur_item, STANDOUT, YES);
  56.                 break;
  57.  
  58.             case KEY_RIGHT:
  59.                 if (Mp -> columns == 1)
  60.                     break;
  61.  
  62.                 draw_item(M2p, cur_item, NORMAL, NO);
  63.  
  64.                 factor = MAX_IROWS / Mp -> spacing;
  65.                 if (cur_item + factor < Mp -> nitems)
  66.                     cur_item += factor;
  67.                 else
  68.                     cur_item %= factor;
  69.  
  70.                 draw_item(M2p, cur_item, STANDOUT, YES);
  71.                 break;
  72.                 
  73.             case KEY_LEFT:
  74.                 if (Mp -> columns == 1)
  75.                     break;
  76.                 draw_item(M2p, cur_item, NORMAL, NO);
  77.  
  78.                 factor = MAX_IROWS / Mp -> spacing;
  79.                 if (cur_item >= factor)
  80.                     cur_item -= factor;
  81.                 else
  82.                     while (cur_item + factor < Mp -> nitems)
  83.                         cur_item += factor;
  84.  
  85.                 draw_item(M2p, cur_item, STANDOUT, YES);
  86.                 break;
  87.                 
  88.             case KEY_SHOW:
  89.                 show_item(M2p, cur_item, newpath);
  90.                 break;
  91.                 
  92.             case KEY_RUN:
  93.                 if (M2p -> Items[cur_item] -> acttyp == ACT_EXIT)
  94.                     return OK;
  95.                 if (do_item(M2p, cur_item, newpath) == EXITALL)
  96.                     return EXITALL;
  97.  
  98.                 switch(M2p -> Items[cur_item] -> nextcode)
  99.                 {
  100.                     case NXT_FIRST:
  101.                         cur_item = 0;
  102.                         break;
  103.                         
  104.                     case NXT_LAST:
  105.                         cur_item = M2p -> Menu.nitems - 1;
  106.                         break;
  107.                     
  108.                     case NXT_NEXT:
  109.                         if (cur_item < M2p -> Menu.nitems - 1)
  110.                             cur_item++;
  111.                         break;
  112.                         
  113.                     case NXT_DIRECT:
  114.                         cur_item = M2p -> Items[cur_item] -> nextitem;
  115.                         break;
  116.                 }
  117.  
  118.                 draw_menu(M2p, cur_item);   /* redisplay menu */
  119.                 break;
  120.                 
  121.             case K_DIRECT:
  122.                 if ((sel_val - 1) != cur_item)
  123.                 {
  124.                     draw_item(M2p, cur_item, NORMAL, NO);
  125.                     cur_item = sel_val - 1;
  126.                     draw_item(M2p, cur_item, STANDOUT, YES);
  127.                 }
  128.                 break;
  129.  
  130.             case K_SHELL:
  131.                 if (M2p -> Menu.escape == YES ||
  132.                   (M2p -> Menu.escape == DEFAULT && DEF_ESCAPE == YES))
  133.                 {
  134. #if SHELL_PROMPT
  135.                     if (put_msg(0, SH_PROMPT_STR) == ESC)
  136.                         break;
  137. #else
  138.                     move(ERR_ROW, 0);
  139.                     hlight_on();
  140.                     addstr("Invoking shell. . .");
  141.                     hlight_end();
  142. #endif
  143.  
  144.                     pre_shell();        /* set up for shell call    */
  145.                     system(SysShell);    /* run a shell                */
  146.                     post_shell();        /* restore everything        */
  147.  
  148.                     draw_menu(M2p, cur_item);
  149.                 }
  150.                 else
  151.                   put_msg(1, "Sorry, shell escapes are disabled.");
  152.                 break;
  153.  
  154.             case K_EXIT:
  155.                 return OK;
  156.  
  157.             case K_EXITALL:
  158.                 return EXITALL;
  159.  
  160.             case K_VERSION:
  161.                 put_msg(0, " RMENU Menu Interpreter v%s ",
  162.                              VERSION);
  163.                 break;
  164.  
  165.             case K_UNKNOWN:
  166.                 beep();
  167.         }
  168.         refresh();
  169.     }
  170. }
  171.  
  172.  
  173. /************************************************************
  174.  * draw_menu(): 
  175.  *    Display the entire menu, including all prompts,
  176.  *    and titles and help text (if any) for current item
  177.  *    on the screen.
  178.  ************************************************************/
  179.  
  180. Void draw_menu(M2p, curr)
  181. MENU2 *M2p;
  182. int curr;
  183. {
  184.     MENU *Mp = &M2p -> Menu;
  185.     int title_len = strlen(Mp -> title);
  186.     int i, j; 
  187.     
  188.     clear();
  189.  
  190.     move(TITLE_ROW, (SCREEN_COLS - title_len)/2);
  191.     addstr(Mp -> title);    /* Put up menu title */
  192.  
  193.     for (i = 0; i < Mp -> nitems; i++)
  194.         if (i != curr)
  195.             draw_item(M2p, i, NORMAL, NO);
  196.  
  197.     draw_item(M2p, curr, STANDOUT, YES);
  198.  
  199.     move(PROMPT_ROW, 0);
  200.     addstr(MENU_OPTS);
  201.     if (Mp -> escape == YES ||
  202.             (Mp -> escape == DEFAULT && DEF_ESCAPE == YES))
  203.         addstr(MENU_SHELL);
  204.     addstr(MENU_PROMPT);
  205.     getyx(stdscr, echoy, echox);    /* save coords of item # echo area */
  206.         
  207.     refresh();    /* display the window */
  208.  
  209. }
  210.  
  211.  
  212. /************************************************************
  213.  * draw_item():
  214.  *    Display a single item (the current item) of the
  215.  *    specified menu, using the specified video mode.
  216.  *    Display assiciated help text only if "dohelp"
  217.  *    is TRUE.
  218.  ************************************************************/
  219.  
  220. Void draw_item(M2p, item, vid_mode, dohelp)
  221. MENU2 *M2p;
  222. int item, vid_mode, dohelp;
  223. {
  224.     ITEM *Ip = M2p -> Items[item];
  225.     COORDS *Cp = &M2p -> coords[item];
  226.     int j;
  227.  
  228.     move (Cp->ypos, Cp->xpos);
  229.     printw("%2d.", item + 1);
  230.  
  231.     if (vid_mode == STANDOUT)
  232.         hlight_on();
  233.  
  234.     printw(" %s", Ip -> text);
  235.  
  236.     for (j = 0; j < Cp -> spaces_needed; j++)
  237.             addch(' ');
  238.  
  239.     if (vid_mode == STANDOUT)
  240.         hlight_end();
  241.  
  242.  
  243.     if (dohelp == YES)
  244.     {
  245.         move(HELP_ROW0, HELP_COL0);
  246.         if (*Ip -> help)
  247.         {
  248.             addstr(" HELP: ");    /* display "HELP:" text    */
  249.  
  250.             move (HELP_ROW, 0);    /* Erase preivous help text (if any) */
  251.             clrtoeol();
  252.  
  253.             move (HELP_ROW, (80 - strlen(Ip -> help))/2);
  254.             hlight_on();
  255.             addstr(Ip -> help);
  256.             hlight_end();
  257.             clrtoeol();
  258.         }
  259.         else
  260.         {
  261.             addstr("       ");    /* clear help text area    */
  262.             move(HELP_ROW, 0);
  263.         }
  264.         clrtoeol();
  265.     }
  266. }
  267.  
  268.  
  269. /************************************************************
  270.  * get_cmd()
  271.  *    Get a command from the user.
  272.  *    Arrow keys or space returns the appropriate K_ code.
  273.  *    Pressing Enter returns the K_RUN code.
  274.  *    Pressing ! returns the K_SHELL code.
  275.  *    Entering a direct number returns K_DIRECT,
  276.  *    and the sel_val is set (indirectly) to selection number
  277.  *  (1-based).
  278.  ************************************************************/
  279.  
  280. int get_cmd(nitems, curr, sel_val)
  281. int nitems;
  282. int curr;
  283. int *sel_val;
  284. {
  285.     int ch;
  286.     int newval;
  287.     int savy, savx;
  288.  
  289.     static int digits = FALSE;    /* true if digits being entered */
  290.     
  291.     move(echoy, echox);    /* move to prompt location */
  292.     printw("%d", curr + 1);
  293.     getyx(stdscr, savy, savx);
  294.     clrtoeol();
  295.     move(savy, savx);
  296.     refresh();
  297.     
  298.     while (1)
  299.     {
  300.         ch = getch();
  301.         if (!isdigit(ch))
  302.             digits = FALSE;
  303.         switch (ch)
  304.         {
  305.             case KEY_UP:
  306.             case '\b':        /* WYSE 60s send this for left arrow */
  307.                 clrtoeol();
  308.                 return KEY_UP;
  309.  
  310.             case ' ':
  311.             case KEY_DOWN:
  312. #if UNIX || XENIX
  313.             case '\n':        /* WYSE 60s send this for down arrow */
  314. #endif
  315.                 clrtoeol();
  316.                 return KEY_DOWN;
  317.  
  318.             case KEY_RIGHT:
  319.             case KEY_LEFT:
  320.             case KEY_RUN:
  321.             case KEY_SHOW:
  322.                 return ch;
  323.  
  324.             case 'e':
  325.             case 'E':
  326.                 return K_EXIT;
  327.  
  328.             case 'x':
  329.             case 'X':
  330.                 return K_EXITALL;
  331.                 
  332.             case 'v':
  333.             case 'V':
  334.                 return K_VERSION;
  335.  
  336.             case '!':
  337.                 return K_SHELL;
  338.  
  339.             case ESC:        /* clear digits area */
  340.                 digits = FALSE;
  341.                 move(echoy, echox);    
  342.                 clrtoeol();
  343.                 refresh();
  344.                 break;
  345.                 
  346.             default:        /* handle digits */
  347.                 if (!isdigit(ch))
  348.                     return K_UNKNOWN;
  349.  
  350.                 if (digits && 
  351.                     (newval = *sel_val * 10 + (ch - '0')) <= nitems
  352.                         && newval > 0)
  353.                 {
  354.                     addch(ch);
  355.                     refresh();
  356.                     *sel_val = newval;
  357.                     return K_DIRECT;
  358.                 }
  359.                 else if ( (newval = ch - '0') && newval <= nitems)
  360.                 {
  361.                     digits = TRUE;
  362.                     move(echoy, echox);    
  363.                     addch(ch);
  364.                     clrtoeol();
  365.                     refresh();
  366.                     *sel_val = newval;
  367.                     return K_DIRECT;
  368.                 }
  369.                 else
  370.                 {
  371.                     digits = FALSE;
  372.                     beep();
  373.                 }
  374.         }
  375.     }
  376. }
  377.